"""
病历掌上查接口服务主应用

基于FastAPI构建的医疗报告查询接口服务
"""

import logging
import sys
from contextlib import asynccontextmanager
from typing import AsyncGenerator

from datetime import datetime
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from pydantic import ValidationError

from .core.config import settings
from .core.exceptions import MedicalReportAPIException
from .core.error_codes import ErrorCode
from .api import reports
from .schemas import HealthCheckResponse


# 配置日志
logging.basicConfig(
    level=getattr(logging, settings.log_level.upper()),
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    handlers=[
        logging.StreamHandler(sys.stdout),
        logging.FileHandler("logs/app.log") if settings.is_production else logging.StreamHandler()
    ]
)

logger = logging.getLogger(__name__)


@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
    """应用生命周期管理"""
    # 启动时的操作
    logger.info("=" * 50)
    logger.info(f"启动 {settings.app_name} v{settings.app_version}")
    logger.info(f"环境: {settings.app_env}")
    logger.info(f"调试模式: {settings.debug}")
    logger.info("=" * 50)

    # 可以在这里添加数据库连接、缓存初始化等操作
    try:
        yield
    finally:
        # 关闭时的操作
        logger.info("应用关闭中...")
        # 可以在这里添加资源清理操作
        logger.info("应用已关闭")


def create_app() -> FastAPI:
    """创建FastAPI应用实例"""

    # 创建FastAPI应用
    app = FastAPI(
        title="病历掌上查接口服务",
        description="""
        ## 概述

        病历掌上查接口服务提供医疗报告查询功能，支持检验报告和检查报告的查询。

        ## 主要功能

        ### 1. 报告主信息查询
        - 支持按就诊卡号、身份证号、住院号查询
        - 支持按患者类型（门诊/住院）筛选
        - 支持按时间范围查询
        - 支持按医院ID筛选
        - 返回报告列表，包含基本信息和状态

        ### 2. 报告详情查询
        - 根据报告ID查询详细信息
        - 包含检查结果、参考范围、结论等

        ### 3. 报告统计查询
        - 获取患者的报告统计信息
        - 包含总报告数、各类报告数量等

        ## 接口规范

        ### 基本约定
        - 所有接口的入参/出参的参数名一律禁止使用中文
        - 就诊卡号(medical_card_number)为患者的唯一标识
        - 所有时间格式皆为yyyy-MM-dd HH:mm:ss
        - 即使返回数据为空，也应该保持返回的数据结构完整性
        - 患者性别：男，女。出参的性别属性约定都是汉字

        ### 返回结果格式
        ```json
        {
            "success": true,      // 接口成功返回true，接口失败返回false
            "msg": "成功",        // 成功返回成功或者空，失败返回错误信息
            "code": "10001",      // 参照附二《接口返回代码对照关系》
            "data": {...}        // 业务数据
        }
        ```

        ## 错误码说明

        | 错误码 | 含义 | 备注 |
        |--------|------|------|
        | 10001 | 成功 | |
        | 10002 | 未查询到数据 | |
        | 10003 | 系统错误 | |
        | 20001 | 缺少参数 | |
        | 20002 | 参数类型错误 | |
        | 20003 | 参数无效或格式错误 | |
        | 30001 | 数据库操作异常 | |
        | 40001 | 系统繁忙 | |
        | 50001 | 无权访问该接口 | |
        | 60501 | 身份证号不能为空 | |

        ## 技术支持

        - **作者**: 沈振华
        - **版本**: 1.0.1
        - **更新时间**: 2025-11-11

        ## 使用说明

        1. **认证方式**: 当前为演示环境，无需认证
        2. **请求格式**: JSON格式，POST方法
        3. **响应格式**: JSON格式，统一返回结构
        4. **时间格式**: yyyy-MM-dd HH:mm:ss
        5. **编码格式**: UTF-8

        ## 注意事项

        - 接口返回的敏感报告(is_empty=1)将不会展示详细信息
        - 特殊类型报告有特殊展示形式或处理逻辑
        - 查询时间范围不能超过1年
        - 建议对频繁查询的结果进行缓存
        """,
        version=settings.app_version,
        docs_url="/docs" if settings.debug else None,
        redoc_url="/redoc" if settings.debug else None,
        openapi_url="/openapi.json" if settings.debug else None,
        lifespan=lifespan,
        contact={
            "name": "沈振华",
            "email": "shenzhenhua@example.com",
        },
        license_info={
            "name": "MIT",
            "url": "https://opensource.org/licenses/MIT",
        },
        servers=[
            {
                "url": "http://localhost:8000",
                "description": "开发环境",
            },
            {
                "url": "https://api-test.hospital.com",
                "description": "测试环境",
            },
            {
                "url": "https://api.hospital.com",
                "description": "生产环境",
            },
        ],
    )

    # 配置CORS中间件
    app.add_middleware(
        CORSMiddleware,
        allow_origins=settings.cors_origins,
        allow_credentials=settings.cors_allow_credentials,
        allow_methods=settings.cors_allow_methods,
        allow_headers=settings.cors_allow_headers,
    )

    # 注册异常处理器
    @app.exception_handler(MedicalReportAPIException)
    async def medical_report_exception_handler(request: Request, exc: MedicalReportAPIException):
        """自定义异常处理器"""
        logger.error(f"API异常 - URL: {request.url}, 错误: {exc.message}, 代码: {exc.code}")
        return JSONResponse(
            status_code=exc.status_code,
            content={
                "success": False,
                "msg": exc.message,
                "code": exc.code,
                "data": exc.data
            }
        )

    @app.exception_handler(ValidationError)
    async def validation_exception_handler(request: Request, exc: ValidationError):
        """Pydantic验证异常处理器"""
        logger.error(f"参数验证异常 - URL: {request.url}, 错误: {exc.errors()}")
        return JSONResponse(
            status_code=400,
            content={
                "success": False,
                "msg": "参数验证失败",
                "code": ErrorCode.PARAMETER_INVALID,
                "data": exc.errors()
            }
        )

    @app.exception_handler(Exception)
    async def general_exception_handler(request: Request, exc: Exception):
        """通用异常处理器"""
        logger.error(f"系统异常 - URL: {request.url}, 错误: {str(exc)}", exc_info=True)
        return JSONResponse(
            status_code=500,
            content={
                "success": False,
                "msg": "系统错误",
                "code": ErrorCode.SYSTEM_ERROR,
                "data": None
            }
        )

    # 注册路由
    app.include_router(reports.router)

    # 健康检查端点
    @app.get("/health", response_model=HealthCheckResponse, summary="健康检查")
    async def health_check():
        """健康检查接口"""
        return HealthCheckResponse(
            status="healthy",
            version=settings.app_version,
            timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            environment=settings.app_env,
            dependencies={
                "database": "healthy",
                "redis": "healthy"
            }
        )

    # 根路径
    @app.get("/", summary="服务信息")
    async def root():
        """服务根路径"""
        return {
            "service": settings.app_name,
            "version": settings.app_version,
            "environment": settings.app_env,
            "docs": "/docs" if settings.debug else None,
            "health": "/health"
        }

    return app


# 创建应用实例
app = create_app()


if __name__ == "__main__":
    import uvicorn

    # 创建日志目录
    import os
    os.makedirs("logs", exist_ok=True)

    uvicorn.run(
        "main:app",
        host=settings.host,
        port=settings.port,
        reload=settings.reload,
        log_config=None  # 使用自定义日志配置
    )